/*
 * Valentine Gladstein
 * SOLAR ID 108731583
 * Homework #7
 * CSE214
 * Recitation 03-Phil Ammirato
 * Grading TA: Yanjie Li
 */

import java.io.*;
import java.util.*;

public class Database implements Serializable{

    //The Database class provides a console-driven menu system for manipulating a simulated inventory and transaction history

    private static final long serialVersionUID = 1;
    private static final String FILENAME = "database.obj";

    protected int nextCustomerID;
    protected int nextItemID;
    protected int nextTransactionID;

    protected ItemList items;
    protected CustomerList customers;
    protected TransactionList transactions; 


/**
 * Constructor tries to load a saved Database object. 
 * loadDatabase() is a seperate method to help  
 * impove readability.
 *
 */
    public Database() {
	loadDatabase();
    }

/**
 * Tries to load a saved Database object. 
 * If no saved file is found, a new one is created.
 *
 */
    private void loadDatabase() {
	try {
	    FileInputStream fis = new FileInputStream(FILENAME);
	    ObjectInputStream ois = new ObjectInputStream(fis);

	    Database temp = (Database)ois.readObject();
	    ois.close();

	    this.nextCustomerID = temp.nextCustomerID;
	    this.nextItemID = temp.nextItemID;
	    this.nextTransactionID = temp.nextTransactionID;
	    this.customers = temp.customers;
	    this.items = temp.items;
	    this.transactions = temp.transactions;
	    System.out.println("A saved database has been found. Its data has been loaded into this database.");
	}
	catch (Exception e) {            //If file was not found,  a new Database object is created
	    nextCustomerID = 4000;
	    nextItemID = 1000;
	    nextTransactionID = 7000;

	    items = new ItemList();
	    transactions = new TransactionList();
	    customers = new CustomerList(); 
	    System.out.println("No saved database was found. A new(empty) one has been created.");
	}
    }


/**
 * Saves the current Database object.
 *
 */
    private void saveDatabase() {
	try {
	    FileOutputStream fos = new FileOutputStream(FILENAME);
	    ObjectOutputStream oos = new ObjectOutputStream(fos);

	    oos.writeObject((Object)this);
	    oos.close();
	    System.out.println("Saved!");
	}
	catch (Exception e) {            //If file was not written successfully
	    System.out.println("Unscpecified error occurred while saving database.");
	}
    }


/**
 * Prompts user to enter info about a customer to be created.
 * The customer is added and nextCustomerID is incremented.
 * 
 */
    private void addCustomer() {
	String name;
	String address;
	String city;

	System.out.println(" ");
	name = getInput("Enter The customer's name:");
	address = getInput("Enter The customer's street address:");
	city = getInput("Enter The customer's city, state, and zip code:");

	Customer newCust = new Customer(nextCustomerID++, name, address, city);
	customers.add(newCust);
	System.out.println(name + " was added to the customer list.");
    }

/**
 * Prompts user to enter info about a Transaction to be created.
 * The transaction is added and nextTransactionID is incremented.
 * 
 */
    private void addTransaction() {
	int customerID;
	int itemID;
	int quantity;
	String date;

	System.out.println(" ");
	try {
	    customerID = Integer.parseInt(getInput("Enter the customer's memberID:"));
	    itemID = Integer.parseInt(getInput("Enter the itemID:"));
	    quantity =  Integer.parseInt(getInput("Enter the quantity(use negative quantities for returns):"));
	} catch(NumberFormatException E) {
	    System.out.println("Please enter a valid integer.");
	    return;
	}
	if (itemID >= nextItemID || customerID >= nextCustomerID || itemID < 1000 || customerID < 4000) {
	    System.out.println("Customer or item could not be found in the database.");
	    return;
	}
	date = getInput("Enter The transaction date:");
	Transaction newTrans = new Transaction(nextTransactionID++, customerID, itemID, quantity, date);
	transactions.add(newTrans);
	System.out.println("Transaction #" + (nextTransactionID -1) + " was added to the transaction list.");
    }

    /**
     * Prompts user to enter info about an Item to be created.
     * The item is added and nextItemID is incremented.
     * 
     */
    private void addItem() {
	String name;
	int quantity;

	System.out.println(" ");
	name = getInput("Enter The item's name:");
	try {
	    quantity =  Integer.parseInt(getInput("Enter the quantity:"));
	} catch(NumberFormatException E) {
	    System.out.println("Please enter a valid integer.");
	    return;
	}

	Item newItem = new Item(nextItemID++, name, quantity);
	items.add(newItem);
	System.out.println(name + " was added to the item list.");
    }

    public void viewItems() {
	String s = "";
	String input = "";

	items.sortByIDA();
	System.out.println(items);
	s+="\n";
	s+="\n";
	s+="Please make a selection to sort the list:\n";
	s+="\n";
	s+="IA) Sort by ItemID(Ascending)(default)\n";
	s+="ID) Sort bi ItemID(Descending)\n";
	s+="NA) Sort by Item Name(Ascending)(default)\n";
	s+="ND) Sort by Item Name(Descending)\n";
	s+="QA) Sort by Quantity(Ascending)\n";
	s+="QD) Sort by Quantity(Descending)\n";
	s+="M) Retun to main menu\n";
	s+="\n";
	s+="Make a selection:";
	while(true) {
	    input = getInput(s);
	    if (input.equals("na"))
		items.sortByNameA();
	    else if (input.equals("nd"))
		items.sortByNameD();
	    else if (input.equals("qa"))
		items.sortByQuantityA();
	    else if (input.equals("qd"))
		items.sortByQuantityD();
	    else if (input.equals("ia"))
		items.sortByIDA();
	    else if (input.equals("id"))
		items.sortByIDD();
	    else if (input.equals("m"))
		break;
	    else {
		System.out.println("Input not recognized. Please make a valid selection:");
		continue;
	    }
	    System.out.println(items);
	}
    }

    public void viewTransactions() {
	String s = "";
	String input = "";

	transactions.sortByIDA();
	System.out.println(transactions);
	s+="\n";
	s+="\n";
	s+="Please make a selection to sort the list:\n";
	s+="\n";
	s+="TA) Sort by TransactionID(Ascending)(default)\n";
	s+="TD) Sort by TransactionID(Descending)\n";
	s+="MA) Sort by MemberID(Ascending)\n";
	s+="MD) Sort by MemberID(Descending)\n";
	s+="IA) Sort by ItemID(Ascending)\n";
	s+="ID) Sort bi ItemID(Descending)\n";
	s+="M) Retun to main menu\n";
	s+="\n";
	s+="Make a selection:";
	while(true) {
	    input = getInput(s);
	    if (input.equals("ta"))
		transactions.sortByIDA();
	    else if (input.equals("td"))
		transactions.sortByIDD();
	    else if (input.equals("ma"))
		transactions.sortByMemberIDA();
	    else if (input.equals("md"))
		transactions.sortByMemberIDD();
	    else if (input.equals("ia"))
		transactions.sortByItemIDA();
	    else if (input.equals("id"))
		transactions.sortByItemIDD();
	    else if (input.equals("m"))
		break;
	    else {
		System.out.println("Input not recognized. Please make a valid selection:");
		continue;
	    }
	    System.out.println(transactions);
	}
    }


    public void viewCustomers() {
	String s = "";
	String input = "";

	customers.sortByIDA();
	System.out.println(customers);
	s+="\n";	    s+="\n";
	s+="Please make a selection to sort the list:\n";
	s+="\n";
	s+="NA) Sort by Name(Ascending)\n";
	s+="ND) Sort by Name(Descending)\n";
	s+="IA) Sort by ID(Ascending)(default)\n";
	s+="ID) Sort bi ID(Descending)\n";
	s+="M) Retun to main menu\n";
	s+="\n";
	s+="Make a selection:";
	while(true) {
	    input = getInput(s);
	    if (input.equals("na"))
		customers.sortByNameA();
	    else if (input.equals("nd"))
		customers.sortByNameD();
	    else if (input.equals("ia"))
		customers.sortByIDA();
	    else if (input.equals("id"))
		customers.sortByIDD();
	    else if (input.equals("m"))
		break;
	    else {
		System.out.println("Input not recognized. Please make a valid selection:");
		continue;
	    }
	    System.out.println(customers);
	}
    }

    /**
     * Displays the main menu in the standard output and 
     * gets the user's input selection.
     * @return The user's entry, converted to lowercase.
     */
    public static String displayMenu(){

	System.out.println("\n\n-------------------------------");
	System.out.println(" Main Menu");
	System.out.println("-------------------------------");
	System.out.println(" C:  Add Customer");
	System.out.println(" I:  Add Item");
	System.out.println(" R:  Record a return");
	System.out.println(" S:  Record a sale");
	System.out.println(" VC: View customers");
	System.out.println(" VI: View Items");
	System.out.println(" VT: View Transactions");
	System.out.println(" Q:  Quit the pogram");
	System.out.println("-------------------------------\n");
	System.out.println("");

	return getInput("Please make a selection: ");

    }

    /**
     * A helper method used internally to read user input from the standard input
     * @param prompt: the prompt to be displayed before accepting user input
     * @return a string containing the user's input
     */
    public static String getInput(String prompt) {
	System.out.print(prompt + " ");
	String s = "";
	InputStreamReader isr = new InputStreamReader(System.in);
	BufferedReader br = new BufferedReader(isr);
	try {
	    s = br.readLine();

	} catch (IOException e) {}
	return s.toLowerCase();
    }

    /**
     * Provides a way for the user to save the database 
     * and quit the program gracefully
     *
     */
    private void quit() {
	System.out.println("\nSaving database....");
	saveDatabase();
        System.out.println("\nTerminating program normally....\n\n");
        System.exit(0);
    }

    /**
     * Provides a menu-driven system for manipulating the 
     * database. This method loops back to displaying 
     * the menu after every action the user takes.
     *
     */ 
    public static void main(String[] args) {	
	Database driver = new Database();

	while (true){
	    String str = displayMenu();
	    if (str.equals("c")) 
		driver.addCustomer();
	    else if (str.equals("i"))
		driver.addItem();
	    else if (str.equals("r"))
		driver.addTransaction();
	    else if (str.equals("s"))
		driver.addTransaction();
	    else if (str.equals("vc"))
		driver.viewCustomers();
	    else if (str.equals("vi"))
		driver.viewItems();
	    else if (str.equals("vt"))
		driver.viewTransactions();
	    else if (str.equals("q"))
		driver.quit();
	    else System.out.println("Input not recognized. Please make a valid selection:");
	}
	
    }
}